#include "hal_data.h"
#include <stdio.h>
#include "oled.h"
#include "bmp.h"


FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    if(p_args->event == UART_EVENT_TX_COMPLETE)
    {
        uart_send_complete_flag = true;
    }
}

#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else

#endif


PUTCHAR_PROTOTYPE
{
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){}
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    for(int i=0;i<size;i++)
    {
        __io_putchar(*pBuffer++);
    }
    return size;
}


/* Callback function */
i2c_master_event_t i2c_event = I2C_MASTER_EVENT_ABORTED;
uint32_t  timeout_ms = 1000000;
void i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    i2c_event = I2C_MASTER_EVENT_ABORTED;
    if (NULL != p_args)
    {
        /* capture callback event for validating the i2c transfer event*/
        i2c_event = p_args->event;
    }
}

uint8_t failed = 0;
uint8_t button_num = 0;
uint8_t get_key_val(void)
{

    bsp_io_level_t p_port_value_pin_000;
    R_IOPORT_PinRead(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_00, &p_port_value_pin_000);
    if(p_port_value_pin_000)
    {
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_11, BSP_IO_LEVEL_LOW);
        button_num=0;
    }
    else//按下按键LED亮
    {
        R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_01_PIN_11, BSP_IO_LEVEL_HIGH);
        if(button_num<10)
        {
            button_num++;
            return 1;
        }
        else
        {
            return 2;
        }



    }



    return 0;
}


/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */

    /* Open the transfer instance with initial configuration. */
    err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
    assert(FSP_SUCCESS == err);

    printf("hello\n");

    /* Initialize the I2C module */
    err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);

    /* Initialize the I2C module */
    err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
    /* Handle any errors. This function should be defined by the user. */
    assert(FSP_SUCCESS == err);

    OLED_Init();              // 初始化 OLED 屏幕（发送初始化命令序列，设置工作模式）
    OLED_Clear();             // 清空显存（OLED_GRAM），并刷新，使屏幕全黑
    OLED_ColorTurn(0);        // 设置显示颜色模式：0 为正常显示，1 为反色显示（黑白反转）
    OLED_DisplayTurn(0);      // 设置显示方向：0 为正常方向，1 为上下翻转显示

    OLED_Clear();//清空 OLED 显存
    OLED_ShowString(0, 0, "RA4M2", 16, 1);//在坐标 (0,0) 显示RA4M2，字体16，正显
    OLED_ShowString(0, 16, "hello world!", 16, 0);//在坐标 (0,16) 显示hello world!，字体16，反显
    OLED_Refresh();// 将 OLED_GRAM 显存内容刷新到 OLED 屏幕上，显示数字和字符串

    R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);  // 延时 2000 毫秒

    OLED_ShowPicture(0, 32, 117, 19, BMP3, 1);                // 在 OLED 屏幕的 (x=0, y=32) 位置显示一张宽 117、高 19 像素的图片 BMP3，正常模式显示
    OLED_Refresh();                                           // 将图片内容从缓冲区刷新到 OLED 屏幕上，真正显示出来
    R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);  // 延时 200 毫秒

    OLED_DrawCover();
    OLED_Refresh();                                           // 将图片内容从缓冲区刷新到 OLED 屏幕上，真正显示出来
    R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);  // 延时 200 毫秒

    OLED_Clear();
    OLED_Refresh();

    uint8_t key_num = 0;
    unsigned char cactus_category = 0;
    unsigned char cactus_length = 8;
    unsigned int score = 0;
    unsigned int highest_score = 0;
    int height = 0;
    int cactus_pos = 128;
    unsigned char cur_speed = 30;

    char reset = 0;



    while(1)
    {
        if (failed == 1)
        {
            OLED_DrawRestart();
            OLED_Refresh();
            key_num = get_key_val();
            if (key_num == 2)
            {
                if (score > highest_score) highest_score = score;
                score = 0;
                failed = 0;
                height = 0;
                reset = 1;
                OLED_DrawDinoJump(reset);
                OLED_DrawCactusRandom(cactus_category, reset);
                OLED_Clear();
                OLED_Refresh();
            }
            continue;
        }



        score ++;
        if (height <= 0) key_num = get_key_val();
        // 显示地面
        OLED_DrawGround();
        // 绘制云朵
        OLED_DrawCloud();

        if (height>0 || key_num == 1)
            height = OLED_DrawDinoJump(reset);
        else
            OLED_DrawDino();

        cactus_pos = OLED_DrawCactusRandom(cactus_category, reset);

        if(cactus_category == 0) cactus_length = 8;
        else if(cactus_category == 1) cactus_length = 16;
        else cactus_length = 24;

        if (cactus_pos + cactus_length < 0)
        {
          cactus_category = rand()%4;
            OLED_DrawCactusRandom(cactus_category, 1);

        }

        if ((height < 16) && ( (cactus_pos>=16 && cactus_pos <=32) || (cactus_pos + cactus_length>=16 && cactus_pos + cactus_length <=32)))
        {
            failed = 1;
        }

        OLED_ShowString(35, 0, "HI:", 12, 1);//
        OLED_ShowNum(58,0,highest_score,5,12,1);
        OLED_ShowNum(98, 0, score, 5, 12,1);
        OLED_Refresh();
        reset = 0;

        cur_speed = score/50;
        if (cur_speed > 29) cur_speed = 29;
        R_BSP_SoftwareDelay (30 - cur_speed, BSP_DELAY_UNITS_MILLISECONDS);

        key_num = 0;

    }






#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);

#if BSP_CFG_SDRAM_ENABLED

        /* Setup SDRAM and initialize it. Must configure pins first. */
        R_BSP_SdramInit(true);
#endif
    }
}

#if BSP_TZ_SECURE_BUILD

FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
FSP_CPP_FOOTER

#endif
